package com.liachen.stock.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.liaochong.myexcel.core.DefaultExcelBuilder;
import com.github.liaochong.myexcel.core.SaxExcelReader;
import com.google.common.base.Splitter;
import com.liachen.common.enums.StockSummaryType;
import com.liachen.common.util.ExcelUtil;
import com.liachen.stock.controller.req.QueryStockSummaryReq;
import com.liachen.stock.entity.Annual;
import com.liachen.stock.entity.StockSimple;
import com.liachen.stock.entity.StockSummaryInfo;
import com.liachen.stock.entity.User;
import com.liachen.stock.entity.UserStockInfo;
import com.liachen.stock.ext.CnInfoService;
import com.liachen.stock.ext.KLineApiService;
import com.liachen.stock.ext.THSExtService;
import com.liachen.stock.service.IUserService;
import com.liachen.stock.service.IUserStockInfoService;
import com.liachen.stock.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class StockServiceImpl implements StockService {
    private static final String NEED_FOLLOW = "追踪可看";
    @Autowired
    private IUserService userService;
    @Autowired
    private IUserStockInfoService userStockInfoService;
    @Autowired
    private THSExtService thsExtService;
    @Autowired
    private KLineApiService kLineApiService;
    @Autowired
    private CnInfoService cnInfoService;
    @Override
    public void saveStockInfo(String type) {
        QueryWrapper queryUser = new QueryWrapper<User>().eq("type", type).apply("modify_time > DATE({0}) AND modify_time <= DATE_ADD({0}, INTERVAL 1 DAY)", DateUtil.beginOfDay(new Date()).toJdkDate());
        List<User> userList = userService.list(queryUser);
        if (CollectionUtil.isEmpty(userList) || userList.size() < 100) {
            userList = saveUser(type);
        }
        userList.forEach(user -> {
            QueryWrapper queryStock = new QueryWrapper<UserStockInfo>().eq("user_id", user.getUserId()).apply("modify_time > DATE({0}) AND modify_time <= DATE_ADD({0}, INTERVAL 1 DAY)", DateUtil.beginOfDay(new Date()).toJdkDate());
            List<UserStockInfo> stockInfoList = userStockInfoService.list(queryStock);
            if (CollectionUtil.isEmpty(stockInfoList)) {
                saveStock(user);
            }
        });
    }

    @Override
    public void exportStockSummaryInfo(String fileName, QueryStockSummaryReq req, HttpServletResponse response) {
        req.setStartDate(DateUtil.beginOfDay(new Date()));
        List<StockSummaryInfo> stockSummaryInfoList = userStockInfoService.querySummaryInfo(req);
        String fileNameWithDate = String.format("%s_%s", DateUtil.formatDate(new Date()), fileName);
        ExcelUtil.export(stockSummaryInfoList, StockSummaryInfo.class, fileNameWithDate, response);
    }

    @Override
    public void exportAllStockSummary(String fileName, Integer num, HttpServletResponse response) {
        Date startDate = DateUtil.beginOfDay(new Date());
        String todayDateStr = DateUtil.format(startDate, DatePattern.NORM_DATE_PATTERN);
        //历史总市值
        QueryStockSummaryReq historyTotal = QueryStockSummaryReq.builder().startDate(startDate).num(Objects.isNull(num) ? null : num).orderBy("sum(market_value) DESC").build();
        List<StockSummaryInfo> historyTotalList = userStockInfoService.querySummaryInfo(historyTotal);
        Workbook historyTotalWorkbook = DefaultExcelBuilder.of(StockSummaryInfo.class).sheetName(StockSummaryType.HISTORY_TOTAL.getName()).fixedTitles().build(historyTotalList);

        //历史持有人数
        QueryStockSummaryReq historyHoldNum = QueryStockSummaryReq.builder().startDate(startDate).num(Objects.isNull(num) ? null : num).orderBy("count(1) DESC").build();
        List<StockSummaryInfo> historyHoldNumList = userStockInfoService.querySummaryInfo(historyHoldNum);
        Workbook historyHoldNumWorkbook = DefaultExcelBuilder.of(StockSummaryInfo.class, historyTotalWorkbook).sheetName(StockSummaryType.HISTORY_HOLD_NUM.getName()).build(historyHoldNumList);

        //当日总市值
        QueryStockSummaryReq todayTotal = QueryStockSummaryReq.builder().startDate(startDate).num(Objects.isNull(num) ? null : num).orderBy("sum(market_value) DESC").buyDate(DateUtil.format(startDate, DatePattern.NORM_DATE_PATTERN)).build();
        List<StockSummaryInfo> todayTotalList = userStockInfoService.querySummaryInfo(todayTotal);
        Workbook todayTotalWorkbook = DefaultExcelBuilder.of(StockSummaryInfo.class, historyHoldNumWorkbook).sheetName(StockSummaryType.TODAY_TOTAL.getName()).build(todayTotalList);

        //当日总人数
        QueryStockSummaryReq todayHoldNum = QueryStockSummaryReq.builder().startDate(startDate).num(Objects.isNull(num) ? null : num).orderBy("count(1) DESC").buyDate(DateUtil.format(startDate, DatePattern.NORM_DATE_PATTERN)).build();
        List<StockSummaryInfo> todayHoldNumList = userStockInfoService.querySummaryInfo(todayHoldNum);
        Workbook todayHoldNumWorkbook = DefaultExcelBuilder.of(StockSummaryInfo.class, todayTotalWorkbook).sheetName(StockSummaryType.TODAY_HOLD_NUM.getName()).build(todayHoldNumList);
        ExcelUtil.export(todayHoldNumWorkbook, StringUtils.isBlank(fileName) ? todayDateStr : String.format("%s_%s", todayDateStr, fileName), response);
    }

    @Override
    public void queryStockTodayInfo(MultipartFile file, HttpServletResponse response) {
        try {
            Workbook workbook = null;
            for (StockSummaryType type : StockSummaryType.values()) {
                List<StockSummaryInfo> stockSummaryInfoList = SaxExcelReader.of(StockSummaryInfo.class).sheet(type.getName()).rowFilter(row -> row.getRowNum() != 0).read(file.getInputStream());
                List<StockSimple> stockSimpleList = new ArrayList<>();
                for (StockSummaryInfo stockSummaryInfo : stockSummaryInfoList) {
                    if (Objects.nonNull(stockSummaryInfo.getCode())) {
                        QueryWrapper<UserStockInfo> queryStock = new QueryWrapper<UserStockInfo>().eq("code", stockSummaryInfo.getCode()).apply("modify_time > DATE({0}) AND modify_time <= DATE_ADD({0}, INTERVAL 1 DAY)", DateUtil.beginOfDay(new Date()).toJdkDate()).last("limit 1");
                        UserStockInfo userStockInfo = userStockInfoService.getOne(queryStock);
                        StockSimple stockSimple;
                        if (Objects.isNull(userStockInfo)) {
                            stockSimple = kLineApiService.getStockTodayInfo(stockSummaryInfo);
                        } else {
                            stockSimple = convertFrom(userStockInfo);
                        }
                        stockSimpleList.add(stockSimple);
                    }
                }
                if (Objects.isNull(workbook)) {
                    workbook = DefaultExcelBuilder.of(StockSimple.class).fixedTitles().sheetName(type.getName()).build(stockSimpleList);
                } else {
                    workbook = DefaultExcelBuilder.of(StockSimple.class, workbook).fixedTitles().sheetName(type.getName()).build(stockSimpleList);
                }
            }
            ExcelUtil.export(workbook, String.format("%s_%s", DateUtil.formatDate(new Date()), "todayIncrease"), response);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public void downAnnual(String stockNames) throws IOException {
        List<String> stockNameList = Splitter.on(",").splitToList(stockNames);
        stockNameList.stream().forEach(stockName -> {
            Annual annual = null;
            try {
                annual = cnInfoService.queryAnnual(stockName, "");
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
            cnInfoService.downAnnual(annual);
        });
    }

    private StockSimple convertFrom(UserStockInfo userStockInfo) {
        StockSimple stockSimple = new StockSimple();
        stockSimple.setCode(userStockInfo.getCode());
        stockSimple.setName(userStockInfo.getName());
        stockSimple.setIncrease(userStockInfo.getTodayIncrease());
        return stockSimple;
    }

    private void saveStock(User user) {
        List<UserStockInfo> stockInfoList;
        QueryWrapper queryByUserId = new QueryWrapper<UserStockInfo>().eq("user_id", user.getUserId()).eq("type", user.getType());
        if (Objects.nonNull(user.getHaveFollow()) && 0 == user.getHaveFollow()) {
            thsExtService.followUser(user.getUserId().toString(), user.getUsrId().toString(), user.getUserName());
            user.setHaveFollow(1);
            userService.update(user, queryByUserId);
        }
        if (Objects.nonNull(user.getNoStock()) && user.getNoStock() == 0) {
            try {
                stockInfoList = thsExtService.queryUserStockInfoList(user.getUserId());
                //查到同花顺有持仓，更新持仓信息；否则设置user为空仓
                if (CollectionUtil.isNotEmpty(stockInfoList)) {
                    //清楚用户持仓再插入持仓信息
                    QueryWrapper stockWrapper = new QueryWrapper<UserStockInfo>().eq("user_id", user.getUserId());
                    userStockInfoService.remove(stockWrapper);
                    userStockInfoService.saveOrUpdateBatch(stockInfoList);
                } else {
                    user.setNoStock(1);
                    userService.update(user, queryByUserId);
                }
            } catch (Exception e) {
                //报错说明未跟踪，进行跟踪
                thsExtService.followUser(user.getUserId().toString(), user.getUsrId().toString(), user.getUserName());
                user.setHaveFollow(1);
                userService.update(user, queryByUserId);
                log.error(e.getMessage(), e);
            }

        }

    }

    private List<User> saveUser(String type) {
        List<User> userList = thsExtService.queryUserList(type);
        for (User user : userList) {
            try {
                userService.saveOrUpdate(user, new QueryWrapper<User>().eq("user_id", user.getUserId()).eq("type", type));
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return userList;
    }

}
